Skip to content

[Exporter.Prometheus] Add target_info fallback#7238

Merged
martincostello merged 15 commits into
open-telemetry:mainfrom
martincostello:add-target-info-fallback
May 27, 2026
Merged

[Exporter.Prometheus] Add target_info fallback#7238
martincostello merged 15 commits into
open-telemetry:mainfrom
martincostello:add-target-info-fallback

Conversation

@martincostello

Copy link
Copy Markdown
Member

Changes

Add Prometheus text fallback target_info output as a gauge so resource metadata is still exposed as Info-typed metrics are unavailable for PrometheusText exposition format.

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

Add Prometheus text fallback `target_info` output as a gauge so resource metadata is still exposed as Info-typed metrics are unavailable for PrometheusText exposition format.
@github-actions github-actions Bot added pkg:OpenTelemetry.Exporter.Prometheus.AspNetCore Issues related to OpenTelemetry.Exporter.Prometheus.AspNetCore NuGet package pkg:OpenTelemetry.Exporter.Prometheus.HttpListener Issues related to OpenTelemetry.Exporter.Prometheus.HttpListener NuGet package labels May 1, 2026
Comment thread src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md Outdated
Comment thread src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md Outdated
@codecov

codecov Bot commented May 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 89.95%. Comparing base (bce5483) to head (02e7c3a).
✅ All tests successful. No failed tests found.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #7238      +/-   ##
==========================================
- Coverage   90.00%   89.95%   -0.06%     
==========================================
  Files         276      276              
  Lines       14106    14120      +14     
==========================================
+ Hits        12696    12701       +5     
- Misses       1410     1419       +9     
Flag Coverage Δ
unittests-Project-Experimental 89.88% <100.00%> (-0.02%) ⬇️
unittests-Project-Stable 89.88% <100.00%> (-0.02%) ⬇️
unittests-UnstableCoreLibraries-Experimental 47.80% <100.00%> (+0.07%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...tpListener/Internal/PrometheusCollectionManager.cs 91.73% <100.00%> (+0.13%) ⬆️
...heus.HttpListener/Internal/PrometheusSerializer.cs 98.83% <100.00%> (+0.03%) ⬆️

... and 2 files with indirect coverage changes

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Prometheus text/plain fallback for resource metadata by emitting target_info as a gauge (value 1) when Info-typed metric families aren’t available in the Prometheus text exposition format.

Changes:

  • Emit target_info as # TYPE target_info gauge / # HELP target_info ... for Prometheus text output while keeping OpenMetrics # TYPE target info.
  • Cache target_info serialization separately for plain text vs OpenMetrics responses.
  • Update HttpListener and AspNetCore integration tests + exporter changelogs to reflect the new plaintext output.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/OpenTelemetry.Exporter.Prometheus.HttpListener.Tests/PrometheusHttpListenerTests.cs Updates expected scrape output to include plaintext target_info gauge.
test/OpenTelemetry.Exporter.Prometheus.AspNetCore.Tests/PrometheusExporterMiddlewareTests.cs Updates expected scrape output to include plaintext target_info gauge.
src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusSerializer.cs Makes WriteTargetInfo switch between OpenMetrics info vs plaintext gauge family names.
src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusCollectionManager.cs Writes/caches target_info for both formats and splits cached lengths by format.
src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md Documents the fallback behavior addition.
src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md Documents the fallback behavior addition.
Comments suppressed due to low confidence (1)

src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusSerializer.cs:472

  • WriteTargetInfo always appends a comma for each resource attribute and then unconditionally does cursor-- to overwrite the last comma. If resource is not reference-equal to Resource.Empty but has zero attributes (e.g., Resource.Empty.Merge(Resource.Empty) returns a new empty Resource), this will overwrite the { and emit invalid exposition (target_info} 1). Track whether any labels were written (or check for an empty attribute collection) and either omit braces/commas or skip emitting the metric when there are no attributes.
        cursor = WriteAsciiStringNoEscape(buffer, cursor, "target_info");
        buffer[cursor++] = unchecked((byte)'{');

        foreach (var attribute in resource.Attributes)
        {
            cursor = WriteLabel(buffer, cursor, attribute.Key, attribute.Value);

            buffer[cursor++] = unchecked((byte)',');
        }

        cursor--; // Write over the last written comma

        buffer[cursor++] = unchecked((byte)'}');

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@martincostello martincostello marked this pull request as ready for review May 1, 2026 20:38
@martincostello martincostello requested a review from a team as a code owner May 1, 2026 20:38
@martincostello martincostello enabled auto-merge May 4, 2026 09:28
@martincostello martincostello added the keep-open Prevents issues and pull requests being closed as stale label May 8, 2026
@Kielek

Kielek commented May 19, 2026

Copy link
Copy Markdown
Member

From Codex:
[P2] src/OpenTelemetry.Exporter.Prometheus.HttpListener/Internal/PrometheusCollectionManager.cs:238 now calls WriteTargetInfo for the default text/plain path too. WriteTargetInfo only skips the Resource.Empty singleton, so a reachable empty-but-not-singleton resource, for example one returned by a detector or built from empty attributes, writes no labels and then cursor-- overwrites {, producing invalid exposition like target_info} 1. This was already risky for OpenMetrics, but this PR extends it to the default scrape format. Guard on empty resource.Attributes or handle the no-label sample explicitly, and add a plaintext regression test.

Fix generated corrupted metrics if no resources are present.
@martincostello

Copy link
Copy Markdown
Member Author

Feedback addressed.

Wait until all metrics are present, not just one.
Comment thread src/OpenTelemetry.Exporter.Prometheus.HttpListener/CHANGELOG.md Outdated
Comment thread src/OpenTelemetry.Exporter.Prometheus.AspNetCore/CHANGELOG.md Outdated
@martincostello martincostello added this pull request to the merge queue May 26, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch May 26, 2026
@martincostello martincostello enabled auto-merge May 27, 2026 08:05
@martincostello martincostello added this pull request to the merge queue May 27, 2026
Merged via the queue into open-telemetry:main with commit ca775cf May 27, 2026
75 checks passed
@martincostello martincostello deleted the add-target-info-fallback branch May 27, 2026 08:38
@martincostello martincostello removed the keep-open Prevents issues and pull requests being closed as stale label Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg:OpenTelemetry.Exporter.Prometheus.AspNetCore Issues related to OpenTelemetry.Exporter.Prometheus.AspNetCore NuGet package pkg:OpenTelemetry.Exporter.Prometheus.HttpListener Issues related to OpenTelemetry.Exporter.Prometheus.HttpListener NuGet package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants